#pragma once

#include <vector>
#include <set>
#include <unistd.h>
#include <string>

#include "tnet.h"
#include "address.h" 

/**
 example:
  	void onConnEvent(const ConnectionPtr_t& conn, ConnEvent event, const void* context)
	{
		const StackBuffer* buffer = static_cast<const StackBuffer*>(context);
		int n;
    	switch(event)
    	{
    		case Conn_EstablishedEvent:
    			//TODO
    			break;
        	case Conn_ReadEvent:
        		//TODO
        		break;
        	default:
            	break;
    	}
    	return;
	}

	main()
	{
		TcpServer ts;
		ts.startup(
				Address(port),
				std::bind(&onConnEvent,
				shared_from_this(),_1, _2, _3),
				maxprocess);
		return;
	}
*/

namespace tnet
{
    class Address;
    class IOLoop;
    class Process;
    //class ConnChecker;
    
    class TcpServer : public nocopyable
    {
    public:
        TcpServer();
        ~TcpServer();
        
        void start(const Address& addr, const ConnEventCallback_t& callback,size_t maxProcess = 1);
        int  listen(const Address& addr, const ConnEventCallback_t& callback);
        void start(size_t maxProcess = 1);
        void stop();
        
        inline IOLoop* getLoop() { return m_loop; }
        inline void setRunCallback(const ServerRunCallback_t& callback) { m_runCallback = callback; }
        //timeout is second
        inline void setMaxIdleTimeout(int timeout) { m_maxIdleTimeout = timeout; }
        inline void setEpollET(bool epollet){m_et = epollet;};
        inline void setReuseport(bool reuseport=true){ m_reuseport = reuseport;};
        inline void setUnsock(){ m_isunsock = true; };
        inline void setUnpath(const string& path){ m_unpath = path; };
        inline void setCpuaffinity(bool on) { m_affinity = on; };
    private:
        void run();
        void onRun();
        void onStop();
        void onSignal(const SignalerPtr_t& signaler, int signum);
        void onIdleConnCheck(const TimingWheelPtr_t& wheel, const WeakConnectionPtr_t& conn);
        void onNewConnection(IOLoop* loop, int fd, const ConnEventCallback_t& callback);

    private:
        IOLoop* m_loop;
        bool m_et;
        
        ProcessPtr_t m_process;

        std::vector<AcceptorPtr_t> m_acceptors;

        SignalerPtr_t m_signaler;

        int m_maxIdleTimeout;
        TimingWheelPtr_t m_idleWheel;

        std::set<pid_t> m_workers;

        bool m_running;

        ConnEventCallback_t m_connEventCallback;
        ServerRunCallback_t m_runCallback;        
		bool m_reuseport;
        bool m_isunsock;
        string m_unpath;
		uint16_t m_port;
        bool m_affinity;
    };
}
